package frame;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JTextArea;

import models.BaseModel;
import models.ClassVector;
import models.NewTree;
import models.ResultByReverseTree;
import models.ResultByTree;
import models.ResultByVoting;
import models.ResultByVotingNoNGS;
import models.ResultNonProb;
import static util.ModelUtil.*;

import org.apache.log4j.Logger;

import util.Log4jUtil;
import util.ModelUtil;
import util.ResultTable;
import util.SystemUtil;
import util.ProgressBar.Task;
import feature.util.ArgumentMap;
import feature.util.CLutility;

/**
 * @author Rishi Das Roy
 *
 * @Organization Institute Of Genomics & Integrative Biology
 */
public class Executer {

	public Executer(String[] pArgs) throws Exception {
		super();
		mArgumentMap = CLutility.argumentsToMap(pArgs, "=");
		if (!validate(mArgumentMap)) {
			// System.err.println(HELP_MESSAGE);
			throw new Exception("Invalid parameter");
		} else {
			Log4jUtil.reconfigure(mWrkSpc.getAbsolutePath() + File.separator
					+ mWrkSpc.getName() + ".log");
		}
	}

	private void execute() throws Exception {

		BaseModel[] predModel = ModelUtil.getModels();
		int lCustomModel = 5;
		ResultTable[] tableModel = new ResultTable[1];
		// Generate features

		FeatureHandler lFH = new FeatureHandler(mFilePaths, mLabels, mWrkSpc);

		// for each classifier
		int progress = 4;
		for (BaseModel model : predModel) {
			model.predict(lFH, mWrkSpc);
		}

		List<String> resultPaths = new ArrayList<String>();
		// if(mLabelInfo){
		for (BaseModel model : predModel) {
			String path = mWrkSpc.getAbsolutePath() + File.separator
					+ model.getName() + "_performance.csv";
			resultPaths.add(path);
			model.getResult().writeResult(path);
		}
		String path = mWrkSpc.getAbsolutePath() + File.separator + "tree";

		path = mWrkSpc.getAbsolutePath() + File.separator + "Voting_No_Prob";
		// resultPaths.add(path+"_performance.csv");
		tableModel[0] = ResultNonProb.decision(predModel, path, lFH);
		tableModel[0].saveResult(mFilePaths[0]+".csv");
		SystemUtil.deleteDir(mWrkSpc);

	}

	private void summaryResult(List<String> resultPaths) throws IOException {
		BufferedWriter lBw = new BufferedWriter(new FileWriter(mWrkSpc
				.getAbsolutePath()
				+ File.separator + "summary.csv"));
		for (String string : resultPaths) {
			File file = new File(string);
			BufferedReader lBr = new BufferedReader(new FileReader(file));
			String line;
			lBw.write(file.getName() + System.getProperty("line.separator"));
			while ((line = lBr.readLine()) != null) {
				lBw.write(line + System.getProperty("line.separator"));
			}
			lBw.write(System.getProperty("line.separator"));
			lBw.write(System.getProperty("line.separator"));
			lBw.write(System.getProperty("line.separator"));
			lBw.write(System.getProperty("line.separator"));
		}
		lBw.close();
	}

	private boolean validate(ArgumentMap pArgumentMap)
			throws FileNotFoundException, IOException, Exception {
		boolean isOK = true;
		/*
		 * for (String string : PREFIXES) { String arg =
		 * pArgumentMap.get(string); if(arg==null){ System.err.println(" -i, -w
		 * are mandatory.\n"); return false; } }
		 */
		mFilePaths = pArgumentMap.get("-i").split(",");
		for (String string : mFilePaths) {
			File inPutFile = new File(string);
			if (!inPutFile.exists() && !inPutFile.canRead()
					&& !inPutFile.isFile()) {
				isOK = false;
				throw new Exception(string
						+ " does not exist or can not be read or not a file");
			}
		}


		  if(pArgumentMap.get("-l") != null)
			  mLabels =pArgumentMap.get("-l").split(",");
		  else {
			  mLabelInfo = false;
			  mLabels =new String[mFilePaths.length];
			  for (int i = 0; i < mLabels.length;i++) {
				  mLabels[i] = "0";
			  }
		  }



		 /* if(mFilePaths.length != mLabels.length){ System.err.println("inequal
		  number of input files and labels"); isOK = false; }
*/

		/*
		 * String l1_label = null, l2_label = null; for (String string :
		 * mLabels) { if(l1_label == null){ l1_label=string; }else if(l2_label ==
		 * null){ l2_label = string; }else if(!l1_label.equals(string) &&
		 * !l2_label.equals(string)){ System.err.println("Can handle only binary
		 * data"); isOK = false; } }
		 */

		mWrkSpc = new File(pArgumentMap.get("-w"));
		if (!mWrkSpc.exists()) {
			mWrkSpc.mkdirs();
		} else if (!mWrkSpc.isDirectory() && mWrkSpc.list().length != 0) {
			isOK = false;
			throw new Exception("Failed to create files.");

		}

		isOK = FeatureHandler.validateFastaFile(mFilePaths);

		mRelationName = pArgumentMap.get("-r") != null ? pArgumentMap.get("-r")
				: mWrkSpc.getName();

		// TODO validate input files
		return isOK;
	}

	private static Logger log = Logger.getLogger(Executer.class);

	private static final String HELP_MESSAGE = "Usage of GroSubPredictor \n\n"
			+ "-i:	input files: in fasta format separated by ',' \n"
			+ "-w:	workspace: output directory; to save intermediate/output files\n"
			// + "-r: dataset name: default 'workspace' directory name \n"
			+ "-l:	class label; separated by ',' for each input file.\n\n"
			+ "-h:  display this message\n\n"
			+ " A log.txt will be created which will contain the runtime log messages.\n"
			+ " Example command 'java -jar BioClassifier.jar -i=filePath1,filePath2 -l=pos,neg -w=dirPath\n"
			+ " For any further information & feedback mail to rishi.das@igib.in, ddash@igib.res.in";

	private static final String[] PREFIXES = { "-i", "-w" };

	private String[] mFilePaths;

	private String[] mLabels;

	private File mWrkSpc;

	private String mRelationName;

	private ArgumentMap mArgumentMap;

	private boolean mLabelInfo = true;

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {

		log.debug("Arguments");
		for (String string : args) {
			log.debug(string);
			if (string.equals("-h")) {
				System.out.println(HELP_MESSAGE);
				return;
			}
		}
		String tmpDir = SystemUtil.getNewTmpDir();
		String[] args1 = {
				args[0],
				"-w="+ tmpDir };
		try {
			Executer exe = new Executer(args1);
			exe.execute();
		}catch (RuntimeException e) {

			log.error(e);
		} catch (Exception e) {
			log.error("The Exception occured " + e);
			System.err
					.println("An exception has occured for details see the log file ");
			System.err.println(Log4jUtil.getLogFilePath());
			e.printStackTrace();
			Log4jUtil.reset();

		}
		Log4jUtil.reset();

	}

	public ResultTable[] guiExecute(JTextArea mlog, Task task) throws Exception {

		BaseModel[] predModel = ModelUtil.getModels();
		int lCustomModel = 5;
		ResultTable[] tableModel = new ResultTable[predModel.length
				+ lCustomModel];
		// Generate features
		mlog.append("Validating the input");
		FeatureHandler lFH = new FeatureHandler(mFilePaths, mLabels, mWrkSpc);
		mlog.append("\n" + lFH.getId().size() + " protein sequences are found");
		task.setCustomProgress(4);
		// for each classifier
		int progress = 4;
		for (BaseModel model : predModel) {
			mlog.append("\nPredicting " + MODEL_NAMES.get(model.getName()));
			model.predict(lFH, mWrkSpc);
			task.setCustomProgress(progress += 12);
		}

		List<String> resultPaths = new ArrayList<String>();
		// if(mLabelInfo){
		for (BaseModel model : predModel) {
			String path = mWrkSpc.getAbsolutePath() + File.separator
					+ model.getName() + "_performance.csv";
			resultPaths.add(path);
			model.getResult().writeResult(path);
		}
		String path = mWrkSpc.getAbsolutePath() + File.separator + "tree";
		resultPaths.add(path + "_performance.csv");
		tableModel[0] = ResultByTree.decision(predModel, path, lFH);

		path = mWrkSpc.getAbsolutePath() + File.separator + "newTree";
		resultPaths.add(path + "_performance.csv");
		tableModel[1] = NewTree.decision(predModel, path, lFH);

		path = mWrkSpc.getAbsolutePath() + File.separator + "Voting";
		// resultPaths.add(path+"_performance.csv");
		tableModel[2] = ResultByVoting.decision(predModel, path, lFH);

		path = mWrkSpc.getAbsolutePath() + File.separator + "Voting_No_NGS";
		// resultPaths.add(path+"_performance.csv");
		tableModel[3] = ResultByVotingNoNGS.decision(predModel, path, lFH);

		mlog.append("Processing Vote");
		path = mWrkSpc.getAbsolutePath() + File.separator + "Voting_No_Prob";
		// resultPaths.add(path+"_performance.csv");
		tableModel[4] = ResultNonProb.decision(predModel, path, lFH);

		path = mWrkSpc.getAbsolutePath() + File.separator + "Vector";
		ClassVector.decision(predModel, path, lFH);
		/*
		 * ResultByVoting.vote(predModel,path,lFH);
		 *
		 * path = mWrkSpc.getAbsolutePath()+File.separator+"pref";
		 * resultPaths.add(path+"_Result.csv");
		 * ResultByPreference.preference(predModel,path,lFH);
		 */
		for (int i = lCustomModel; i < tableModel.length; i++) {
			tableModel[i] = predModel[i - lCustomModel].getTable();
		}
		//summaryResult(resultPaths);

		//}

		SystemUtil.deleteDir(mWrkSpc);
		return tableModel;

	}

}
